package customerEnter.Frame.JDBCDao;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.jdbc.core.BatchPreparedStatementSetter;

import customerEnter.Frame.DaoDataTransmission.DaoFrameDMLBaseTransmission;
import customerEnter.Frame.DaoDataTransmission.DaoFramePameTransmission;
import customerEnter.Frame.DaoDataTransmission.FrameBeanSuper;
import customerEnter.Frame.DaoDataTransmission.PagingParametersResult;
import customerEnter.Frame.DaoDataTransmission.WebAppsInfo;
import customerEnter.Frame.Enum.FrameDataQueryUse;
import customerEnter.Frame.JDBCDao.Interface.DaoFrameInterface;
import customerEnter.Frame.JDBCDao.Interface.DaoFrameIntermediateLayerInterface;
import customerEnter.Frame.JDBCDao.Interface.InitializationInterface;
import customerEnter.Frame.JDBCDao.daoFrame.DaoFrameTK;
import customerEnter.Frame.JDBCDao.daoFrame.InitializationData;
import customerEnter.Frame.JDBCDao.daoFrame.SqlDataBaseController;
import customerEnter.Frame.JDBCDao.util.DaoFrameUtil;
import customerEnter.Frame.Utils.Log4j;
import customerEnter.tool.WhetherToEmpty;

/**
 * 數據查詢的集合設計 易擴展和進化 使用默認權限
 * 
 * @author S-2-dy
 * @param T
 *            返回的類
 * @param TableNam
 *            要查詢表的名字
 * @param SQLDataBase
 *            查詢的數據庫名字
 */
public class DaoFrame<T, K extends FrameBeanSuper> implements DaoFrameInterface<T, K> {

	DaoFrameIntermediateLayerInterface<T, K>	daoTransmission;

	final static InitializationInterface		initialization;

	static {
		initialization = new InitializationData();
	}

	//
	// @Resource(name = "jdbcTemplateService")
	// public JdbcTemplateService jdbcTemplateService;

	public DaoFrame() {
		Log4j.Log4jOutInfo("初始化：" + this.getClass());
		/**
		 * 初始化中間件方法
		 */
		daoTransmission = initialization.initializationDaoFrameTransmission(daoTransmission);
		/**
		 * 初始化 sql 控制
		 */
		initialization.initializationSqlController();
		/**
		 * new DaoFrameDMLBaseTransmission(DaoFrame.this) 可以獲取當前框架 初始化dml參數
		 */
		// daoFrameDMLBaseTransmission =
		// InitializationData.getInitializationData()
		// .initializationDaoFrameDMLBaseTransmission(new
		// DaoFrameDMLBaseTransmission(), FindTClassName());
	}

	/**
	 * 初始化 數據參數
	 */
	private DaoFramePameTransmission<T, K> getDaoFramePameTransmission() {
		return initialization.initializationDaoFramePameTransmission(new DaoFramePameTransmission<T, K>());
	}

	/**
	 * 查詢接口
	 */
	@SuppressWarnings("rawtypes")
	public PagingParametersResult findConditionQueryTransmission(String Front, String ClassName, String where,
			Class<?> Class, boolean PagingParametersCount, boolean cache, FrameDataQueryUse frameDataQueryUse) {
		DaoFramePameTransmission<T, K> daoFramePameTransmission = getDaoFramePameTransmission();
		daoFramePameTransmission.setFrameDataQueryUse(frameDataQueryUse);
		findCondItiton(Front, ClassName, where, Class, PagingParametersCount, cache, daoFramePameTransmission);
		return daoFramePameTransmission.getPagingParametersResult();
	}

	@SuppressWarnings("unchecked")
	private void findCondItiton(String Front, String ClassName, String where, Class<?> Class,
			boolean PagingParametersCount, boolean cache, DaoFramePameTransmission<T, K> daoFramePameTransmission) {

		DaoFrameDMLBaseTransmission daoFrameDMLBaseTransmission = initializationDaoFrameDMLBaseTransmission(Front,
				ClassName, where, Class, PagingParametersCount, cache);

		if (WhetherToEmpty.ObjectWhetherToEmpty(daoFrameDMLBaseTransmission.getClassName())) {
			daoFrameDMLBaseTransmission.setClassName(getBaseBeans().gettClass());
		}

		daoFramePameTransmission.daoFrameK = (java.lang.Class<K>) getBaseBeans().getkClass();
		daoFramePameTransmission.daoFrameT = (java.lang.Class<T>) getBaseBeans().gettClass();
		daoTransmission.IfEhcache(daoFrameDMLBaseTransmission, daoFramePameTransmission);
	}

	/**
	 * 增加數據
	 */
	public String InsterObject(String DataBase, String TableName, LinkedList<?> values) {
		// jdbcTemplateService.jdbcTemplate.queryForList(sql);
		DaoFramePameTransmission<T, K> daoFramePameTransmission = getDaoFramePameTransmission();
		daoTransmission.setInsertSql(daoFramePameTransmission, DataBase, TableName, values);
		return daoTransmission.IfSqlError(daoFramePameTransmission);
	}

	/**
	 * 添加數據 對象與表的映射
	 * 
	 * @return
	 */
	public String InsertMapping(String DataBase, String Table, Object MappingObject) {
		DaoFramePameTransmission<T, K> daoFramePameTransmission = getDaoFramePameTransmission();
		try {
			daoTransmission.setInsertMappingSql(daoFramePameTransmission, DataBase, Table, MappingObject);
		} catch (Exception e) {
			Log4j.Log4JOutError(e.getMessage());
		}
		return daoTransmission.IfSqlError(daoFramePameTransmission);
	}

	/**
	 * 批量增加數據
	 * 
	 * @throws Exception
	 */
	public Integer InsertBatchData(String DataBase, String TableName, List<?> t, Class<?> class1) throws Exception {
		final List<?> tempBook = t;
		String sql = daoTransmission.SqlInsertBacth(DataBase, TableName, class1);

		EasyBuyDB.getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {
			public void setValues(PreparedStatement ps, int i) throws SQLException {
				Object object = tempBook.get(i);
				Field[] fields = object.getClass().getDeclaredFields();
				int index = 1;
				for (Field field : fields) {
					field.setAccessible(true);
					String name = field.getName();
					if ("serialVersionUID".equals(name)) {
						continue;
					}
					if ("id".equals(name)) {
						continue;
					}
					try {
						Object pObject = field.get(object);
						ps.setObject(index, pObject);
						index++;
					} catch (Exception e) {
						Log4j.Log4JOutError(e.getMessage());
					}
				}

			}

			public int getBatchSize() {
				return tempBook.size();
			}
		});
		return null;
	}

	/**
	 * 查詢統計數據
	 */
	public Integer QueryCount(String sql) {
		return EasyBuyDB.getJdbcTemplate().queryForObject(sql, Integer.class);
	}

	/**
	 * 修改數據 沒有封裝
	 */
	public Integer UpdateObject(String sql) {
		Integer in = 0;
		try {
			in = EasyBuyDB.getJdbcTemplate().update(sql);
		} catch (Exception e) {
			in = 0;
		}
		return in;
	}

	/**
	 * 刪除數據
	 */
	public Integer deleteObject(String sql) {
		Integer in = 0;
		try {
			in = EasyBuyDB.getJdbcTemplate().update(sql);
		} catch (Exception e) {
			in = 0;
		}
		return in;
	};

	/**
	 * 修改數據 對象與表的映射
	 */
	public String UpdateMappingObject(String DataBase, String TableName, Object MappingObject, String where) {
		DaoFramePameTransmission<T, K> daoFramePameTransmission = getDaoFramePameTransmission();
		try {
			daoTransmission.setUpdateMappingSql(daoFramePameTransmission, DataBase, TableName, MappingObject, where);
		} catch (Exception e) {
			Log4j.Log4JOutError(e.getMessage());
		}
		return daoTransmission.IfSqlError(daoFramePameTransmission);
	}

	/**
	 * 獲取類的名字 外部接口要用
	 */
	public String FindTClassName() {
		return daoTransmission.getClassName(getBaseBeans().gettClass());
	}

	/**
	 * 獲取類的名字 外部接口要用
	 */
	public String FindTClassName(Class<?> class1) {
		return daoTransmission.getClassName(class1);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private DaoFrameTK getBaseBeans() {
		DaoFrameTK daoFrameTK = new DaoFrameTK();
		Class c = this.getClass();
		Type t = c.getGenericSuperclass();
		if (t instanceof ParameterizedType) {
			// System.out.println("in if");
			Type[] p = ((ParameterizedType) t).getActualTypeArguments();
			// System.out.println(Arrays.toString(p));
			daoFrameTK.settClass((Class<T>) p[0]);
			daoFrameTK.setkClass((Class<T>) p[1]);
		}
		return daoFrameTK;
	}

	/**
	 * 緩存，默認存在1分鐘
	 */
	public void setCacheTime(int cacheTime, TimeUnit timeUnit) {

	}

	/**
	 * 獲取sql
	 */
	public String SqlAcquire(String DataBase, String DML, String Front, String Rule, String TableName, String where) {
		String sql = DaoFrameUtil.SqlManage(DataBase, DML, Front, Rule, TableName, where);
		return sql.substring(1, sql.length());
	}

	/**
	 * mysql 分頁 limit 從第多少條開始 取多少條數據
	 */
	void MysqlQueryPage(String where, int size, int page, String order, String descOrAsc,
			DaoFrameDMLBaseTransmission daoFrameDMLBaseTransmission) {
		daoFrameDMLBaseTransmission.setWhere("" + SqlDataBaseController.getWhere() + "  " + where + " order by "
				+ order + "  " + descOrAsc + " limit " + (page * size) + "," + size + " ");

	}

	/**
	 * sql分頁
	 */
	void SqlQueryPage(String Front, String ClassName, String where, int size, int page, String order, String descOrAsc,
			DaoFrameDMLBaseTransmission daoFrameDMLBaseTransmission) {

		String sql = "a." + order + " ";
		if (order.contains("NEWID()")) {
			sql = "  NEWID() ";
			descOrAsc = " ";
		}
		String SystemSele = SqlDataBaseController.getDMLSele();
		String SystemRule = SqlDataBaseController.getRule();
		String SystemWhere = SqlDataBaseController.getWhere();
		String nativeSql = SqlAcquire("", SystemSele, Front, SystemRule, ClassName, SqlDataBaseController.getWhere()
				+ where);
		String countSql = SqlAcquire("", SystemSele, "count(*)", SystemRule, ClassName,
				SqlDataBaseController.getWhere() + where);
		daoFrameDMLBaseTransmission.setFront(" TOP " + size + "  * " + ",(" + countSql + ") pagingParametersCount ");
		daoFrameDMLBaseTransmission.setTableName(" (SELECT ROW_NUMBER() OVER (ORDER BY   " + sql + "  " + descOrAsc
				+ " ) AS RowNumber,* FROM ( " + nativeSql + " ) a )   as A ");
		daoFrameDMLBaseTransmission.setWhere(SystemWhere + " and RowNumber > " + (size * page) + "");
	}

	/**
	 * 數據庫的 分頁區分
	 */
	public void QueryPage(String Front, String ClassName, String where, int size, int page, String order,
			String descOrAsc, DaoFrameDMLBaseTransmission daoFrameDMLBaseTransmission) {
		if ("MySQL Connector Java".contains(WebAppsInfo.webDataBase)) {
			MysqlQueryPage(where, size, page, order, descOrAsc, daoFrameDMLBaseTransmission);
		} else if ("Microsoft SQL Server JDBC Driver 3.0".equals(WebAppsInfo.webDataBase)) {
			SqlQueryPage(Front, ClassName, where, size, page, order, descOrAsc, daoFrameDMLBaseTransmission);
		}
	}

	/**
	 * 初始化語句 初始化dml參數
	 */
	public DaoFrameDMLBaseTransmission initializationDaoFrameDMLBaseTransmission(String Front, String ClassName,
			String where, Class<?> Class, boolean PagingParametersCount, boolean cache) {
		DaoFrameDMLBaseTransmission daoFrameDMLBaseTransmission = new DaoFrameDMLBaseTransmission();

		daoFrameDMLBaseTransmission.setClassName(null);
		if (!WhetherToEmpty.ObjectWhetherToEmpty(Class)) {
			daoFrameDMLBaseTransmission.setClassName(Class);
		}

		daoFrameDMLBaseTransmission.setDataBase(SqlDataBaseController.getDataBase());
		daoFrameDMLBaseTransmission.setDML(SqlDataBaseController.getDMLSele());
		daoFrameDMLBaseTransmission.setFront(SqlDataBaseController.getFront());
		if (!WhetherToEmpty.StringWhetherToEmpty(Front)) {
			daoFrameDMLBaseTransmission.setFront(Front);
		}
		daoFrameDMLBaseTransmission.setIfEhcache(cache);
		daoFrameDMLBaseTransmission.setTableName(FindTClassName());
		if (!WhetherToEmpty.StringWhetherToEmpty(ClassName)) {
			daoFrameDMLBaseTransmission.setTableName(ClassName);
		}
		daoFrameDMLBaseTransmission.setRule(SqlDataBaseController.getRule());

		daoFrameDMLBaseTransmission.setWhere(SqlDataBaseController.getWhere());
		if (!WhetherToEmpty.StringWhetherToEmpty(where)) {
			daoFrameDMLBaseTransmission.setWhere(where);
		}
		daoFrameDMLBaseTransmission.setPagingParametersCount(PagingParametersCount);

		return daoFrameDMLBaseTransmission;
	}

}
